package com.yupi.usercenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.usercenter.common.ErrorCode;
import com.yupi.usercenter.exception.BusinessException;
import com.yupi.usercenter.model.Enum.TeamStatusEnum;
import com.yupi.usercenter.model.domain.Team;
import com.yupi.usercenter.model.domain.User;
import com.yupi.usercenter.model.domain.UserTeam;
import com.yupi.usercenter.model.dto.TeamJoinRequest;
import com.yupi.usercenter.model.dto.TeamQuery;
import com.yupi.usercenter.model.dto.TeamUpdateRequest;
import com.yupi.usercenter.model.vo.TeamUserVO;
import com.yupi.usercenter.model.vo.UserVO;
import com.yupi.usercenter.service.TeamService;
import com.yupi.usercenter.mapper.TeamMapper;
import com.yupi.usercenter.service.UserService;
import com.yupi.usercenter.service.UserTeamService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
* @author Administrator
* @description 针对表【team(队伍)】的数据库操作Service实现
* @createDate 2025-08-11 23:35:03
*/
@Service

@Slf4j
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
    implements TeamService{

    @Autowired
    private UserTeamService userTeamService;
    @Autowired
    private     UserService userServiceImpl;
//    @Autowired
//    private TeamService teamService;
    @Autowired
    private UserService userService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 创建队伍
     * @param team 队伍信息
     * @param loginUser 当前登录用户
     * @return 队伍ID
     */
    @Override
@Transactional(rollbackFor = Exception.class)
public long addTeam(Team team, User loginUser) {
    // 1. 请求参数是否为空？
    if (team == null) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }
    // 2. 是否登录，未登录不允许创建
    if (loginUser == null) {
        throw new BusinessException(ErrorCode.NOT_LOGIN);
    }
    final long userId = loginUser.getId();
    // 3. 校验信息
    //   1. 队伍人数 > 1 且 <= 20
    int maxNum = Optional.ofNullable(team.getMaxNum()).orElse(0);
    if (maxNum < 1 || maxNum > 20) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍人数不满足要求");
    }
    //   2. 队伍标题 <= 20
    String name = team.getName();
    if (StringUtils.isBlank(name) || name.length() > 20) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍标题不满足要求");
    }
    //   3. 描述 <= 512
    String description = team.getDescription();
    if (StringUtils.isNotBlank(description) && description.length() > 512) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍描述过长");
    }
    //   4. status 是否公开（int）不传默认为 0（公开）
    int status = Optional.ofNullable(team.getStatus()).orElse(0);
    TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByVale(status);
    if (statusEnum == null) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍状态不满足要求");
    }
    //   5. 如果 status 是加密状态，一定要有密码，且密码 <= 32
    String password = team.getPassword();
    if (TeamStatusEnum.SECRET.equals(statusEnum)) {
        if (StringUtils.isBlank(password) || password.length() > 32) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码设置不正确");
        }
    }
    // 6. 超时时间 > 当前时间
    Date expireTime = team.getExpireTime();
    if (new Date().after(expireTime)) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "超时时间 > 当前时间");
    }
    // 7. 校验用户最多创建 5 个队伍
    // todo 有 bug，可能同时创建 100 个队伍
    QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("userId", userId);
    long hasTeamNum = this.count(queryWrapper);
    if (hasTeamNum >= 5) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户最多创建 5 个队伍");
    }
//    long l = userTeamService.addUserTeam(team, loginUser);
    // 8. 插入队伍信息到队伍表
    team.setId(null);
    team.setUserId(userId);
    boolean result = this.save(team);
    Long teamId = team.getId();
    if (!result || teamId == null) {
//    if (true) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "创建队伍失败");
    }
    // 9. 插入用户  => 队伍关系到关系表
    UserTeam userTeam = new UserTeam();
    userTeam.setUserId(userId);
    userTeam.setTeamId(teamId);
    userTeam.setJoinTime(new Date());
    log.info("准备保存队伍信息: {}", team);
    result = userTeamService.save(userTeam);
    log.info("队伍保存结果: {}, 队伍ID: {}", result, teamId);

    if (!result) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "创建队伍失败");
    }
    // 测试事务回滚 - 这里会始终抛出异常导致事务回滚
//    if (true) {
//        log.warn("测试代码触发异常，事务将回滚");
//        throw new BusinessException(ErrorCode.PARAMS_ERROR, "创建队伍失败");
//    }
    return teamId;
}

    /**
     * 查询队伍列表
     * @param teamQuery 查询条件
     * @param isAdmin 是否为管理员
     * @return 队伍列表
     */
    @Override
    public List<TeamUserVO> listTeams(TeamQuery teamQuery,Boolean isAdmin) {


        QueryWrapper<Team> teamQueryWrapper1 = new QueryWrapper<>();
        if (teamQuery!= null) {

            Long id = teamQuery.getId();

            if ( id != null && id > 0) teamQueryWrapper1.eq("id", id);
            String searchText = teamQuery.getSearchText();
            if (StringUtils.isNotBlank(searchText)){
               teamQueryWrapper1.and(t->t.like("name", searchText))
                       .or(j->j.like("description", searchText));
            }
            if (org.apache.commons.collections.CollectionUtils.isNotEmpty(teamQuery.getIdList())){
                teamQueryWrapper1.in("id", teamQuery.getIdList());
            }
            String name = teamQuery.getName();
            if (StringUtils.isNotBlank(name)) teamQueryWrapper1.like("name", name);
            String description = teamQuery.getDescription();
            if (StringUtils.isNotBlank(description)) teamQueryWrapper1.like("description", description);
            Integer maxNum = teamQuery.getMaxNum();
            if (maxNum != null && maxNum > 0) {
                teamQueryWrapper1.eq("maxNum", maxNum);
            }
            Long userId = teamQuery.getUserId();
            if (userId != null && userId > 0) {
                teamQueryWrapper1.eq("userId", userId);
            }
            Integer status = teamQuery.getStatus();
            TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByVale(status);
            if (statusEnum == null) statusEnum =TeamStatusEnum.PUBLIC   ;
            if(!isAdmin && !statusEnum.equals(TeamStatusEnum.PUBLIC))
                throw new BusinessException(ErrorCode.NO_AUTH,"缺少管理员权限");
              teamQueryWrapper1.eq("status", statusEnum.getValue());

        }
            teamQueryWrapper1.and(t->t.gt("expireTime",new Date()).or().isNotNull("expireTime"));
            List<Team> list = this.list(teamQueryWrapper1);
            if (CollectionUtils.isEmpty(list)) return new ArrayList<>();
            ArrayList<TeamUserVO> teamUserVOS = new ArrayList<>();
//        List<Long> teamidlist = list.stream().map(Team::getId).collect(Collectors.toList());
        for (Team team : list){
                Long userId1 = team.getUserId();
                if (userId1 == null) continue;
                User byId = userServiceImpl.getById(userId1);
                User safetyUser = userServiceImpl.getSafetyUser(byId);
                TeamUserVO teamUserVO = new TeamUserVO();
                BeanUtils.copyProperties(team,teamUserVO);
                if (byId != null) {
                    UserVO userVO = new UserVO();
                    BeanUtils.copyProperties(safetyUser, userVO);
                    teamUserVO.setCreateUser(userVO);
                }
                List<UserTeam> teamList = userTeamService.lambdaQuery().eq(UserTeam::getTeamId, team.getId()).list();
            ArrayList<UserVO> UserVOPartner = new ArrayList<>();
            if(!(teamList == null && !CollectionUtils.isEmpty(teamList))){
                    for (UserTeam team1 : teamList){
                        User byId1 = userServiceImpl.getById(team1.getUserId());
                        if (byId1 == null) continue;
                        User safetyUser1 = userServiceImpl.getSafetyUser(byId1);
                        UserVO userVO = new UserVO();
                        BeanUtils.copyProperties(safetyUser1,userVO);

                        UserVOPartner.add(userVO);
                    }
                }
                teamUserVO.setUsersList(UserVOPartner);



            teamUserVOS.add(teamUserVO);

            }





        return teamUserVOS;
    }

    /**
     * 更新队伍信息
     * @param team 更新的队伍信息
     * @param loginUser 当前登录用户
     * @return 是否更新成功
     */
    @Override
    public boolean updateTeam(TeamUpdateRequest team , User     loginUser ) {
        if (team == null )  throw new BusinessException(ErrorCode.PARAMS_ERROR);

        Long teamId = team.getId();
        Team oldTeam = judeTeamExits(teamId);
        if(oldTeam.getUserId() != loginUser.getId()  && userService.isAdmin(loginUser))
            throw new BusinessException(ErrorCode.NO_AUTH,"没有权限");

        TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByVale(team.getStatus());
        if (statusEnum.equals(team.getStatus()))
        {
            if (StringUtils.isBlank(team.getPassword())){
                throw new BusinessException(ErrorCode.NULL_ERROR,"加密房间必须要密码");
            }

        }
        Team updateTeam = new Team();
        BeanUtils.copyProperties(team,updateTeam);
        boolean b = this.updateById(updateTeam);

        return true;
    }

    private Team judeTeamExits(Long teamId) {
        if (teamId == null  || teamId < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        Team oldTeam = this.getById(teamId);
        if ( oldTeam == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        return oldTeam;
    }

    /**
     * 加入队伍
     * @param teamJoinRequest 加入队伍的请求参数
     * @param httpServletRequest HTTP请求
     * @param loginUser 当前登录用户
     * @return 是否加入成功
     */
    @Override
    public boolean joinTeam(TeamJoinRequest teamJoinRequest, HttpServletRequest httpServletRequest, User loginUser) {
        if (teamJoinRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN,"用户未登录");
        }
        Long id = loginUser.getId();
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("userId", id);
        long count = userTeamService.count(userTeamQueryWrapper);
        if (count > 5){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"最多可加入5个队伍");

        }
        Long teamId = teamJoinRequest.getId();
        if (teamId == null || teamId <0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍id 不存在");
        }
        Team teamById = this.getById(teamId);

        if (teamById == null ){
            throw new BusinessException(ErrorCode.NULL_ERROR,"队伍不存在");
        }
        if (teamById.getExpireTime() != null && teamById.getExpireTime().before(new Date())){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍已经过期");
        }
        TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByVale(teamById.getStatus());
        if (statusEnum.equals(TeamStatusEnum.PRIVATE)){
            throw new BusinessException(ErrorCode.NULL_ERROR,"禁止加入私有");
        }
        userTeamQueryWrapper  = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId", teamId).eq("userId", id);
        long hasUserJoinTeam = userTeamService.count(userTeamQueryWrapper);
        if(hasUserJoinTeam > 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"已加入过");
        }


        String passwordJoin = teamJoinRequest.getPassword();
        if(TeamStatusEnum.SECRET.equals(statusEnum)){
            if (StringUtils.isBlank(passwordJoin) || !passwordJoin.equals(teamById.getPassword())){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码错误");
            }
        }
        userTeamQueryWrapper  = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId", teamId);
        long teamJoniNumber = userTeamService.count(userTeamQueryWrapper);

        if (teamJoniNumber >= teamById.getMaxNum()){
            throw new BusinessException(ErrorCode.NULL_ERROR,"队伍已经满员");
        }

        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(id);
        userTeam.setTeamId(teamId);
        userTeam.setJoinTime(new Date());
        boolean save = userTeamService.save(userTeam);
        return save;

    }

    /**
     * 退出队伍
     *
     * @param teamJoinRequest 退出队伍的请求参数
     * @param httpServletRequest HTTP请求
     * @param loginUser 当前登录用户
     * @return 是否退出成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean quitTeam(TeamJoinRequest teamJoinRequest, HttpServletRequest httpServletRequest, User loginUser) {
        if (teamJoinRequest == null){
            throw new BusinessException(ErrorCode.NULL_ERROR,"请求为空");
        }
        Long teamId = teamJoinRequest.getId();
        if (teamId ==null || teamId <0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍id不存在");
        }
        Team getTeam = this.getById(teamId);
        if (getTeam == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR,"队伍不存在");
        }
        Long userId = loginUser.getId();
        UserTeam userTeam = new UserTeam();
        userTeam.setTeamId(teamId);
        userTeam.setUserId(userId);

        QueryWrapper<UserTeam> objectQueryWrapper = new QueryWrapper<>(userTeam);
        long count = userTeamService.count(objectQueryWrapper);
        if (count ==0 ){
            throw new BusinessException(ErrorCode.NULL_ERROR,"未加入该队伍");
        }
        // TODO: 实现退出队伍的逻辑
        if (countTeamUserByTeamId(teamId) ==1) {
            this.removeById(teamId);
            QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("teamId", teamId);
            return userTeamService.remove(queryWrapper);
        }else {
            if (teamJoinRequest.getId().equals(userId)){
                QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
                userTeamQueryWrapper.eq("teamId", teamId).last("order by id asc limit 2");
                List<UserTeam> teamList = userTeamService.list(userTeamQueryWrapper);
                if (CollectionUtils.isEmpty(teamList) || teamList.size() > 1){
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR,"队伍数据有误");
                }
                UserTeam nextUserTeam = teamList.get(1);
                Long nextUserTeamUserId = nextUserTeam.getUserId();
                Team updateTeam = new Team();
                updateTeam.setId(teamId);
                updateTeam.setUserId(nextUserTeamUserId);
                boolean b = this.updateById(updateTeam);
                if (!b){
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR,"更新队伍数据失败");
                }
                QueryWrapper<UserTeam> userTeamQueryWrapper1 = new QueryWrapper<>();
                userTeamQueryWrapper1.eq("teamId", teamId);
                userTeamQueryWrapper1.eq("UserId",userId);
                return userTeamService.remove(userTeamQueryWrapper1);



            }
        }

    return false;
    }
@Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteTeam(Long id, User loginUser) {
        Team team = judeTeamExits(id);
        Long teamId = team.getId();
        if (teamId.equals(loginUser.getId())){
            QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
            userTeamQueryWrapper.eq("teamId", teamId);
            boolean remove = userTeamService.remove(userTeamQueryWrapper);
            if (!remove){
                throw new BusinessException(ErrorCode.SYSTEM_ERROR,"删除队伍失败");
            }
            return this.removeById(teamId);

        }
        return false;
    }

    private long countTeamUserByTeamId(long teamId) {
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("teamId", teamId);
        return userTeamService.count(queryWrapper);
    }
}